#include "DrawTask.h"
#include "KmyITexture.h"
//#include "glwidget.h"

DrawTask::DrawTask()
{

    tex = NULL;
    point_num = 0;
//    tri_num_s = 0;
//    tris_s = NULL;
//    tri_num_d = 0;
//    tris_d = NULL;
    texcroods = NULL;
    vertices = NULL;
}


DrawTask::DrawTask(KmyITexture *tex,
                   int sx, int sy, int sw, int sh,
                   int dx, int dy, int dw, int dh,
                   int z,
                   float alpha, float angle, int flip)
{
    this->draw_type = DRAW_TYPE_IMAGE_REGION;
    this->tex = tex;

    point_num = 6;
    St_Triangle *tris_s = new St_Triangle[2];
    St_Triangle *tris_d = new St_Triangle[2];

    rectToTri_s(tex, sx, sy, sw, sh, flip, &tris_s[0]);

    rectToTri_d(dx, dy, dw, dh, &tris_d[0]);

    this->z = z;
    this->alpha = alpha;
    this->angle = angle;
//    this->flip = flip;

    toVertexAttribBuff(2, tris_s, tris_d);

    delete[] tris_s;
    delete[] tris_d;
}

DrawTask::DrawTask(KmyITexture *tex,
                   int sx1, int sy1, int sx2, int sy2, int sx3, int sy3,
                   int dx1, int dy1, int dx2, int dy2, int dx3, int dy3,
                   int z, float alpha){
    draw_type = DRAW_TYPE_IMAGE_TRIANGLE;
    this->tex = tex;
    this->z = z;
    this->alpha = alpha;
    this->angle = 0;

    point_num = 3;
    int tri_num_s = 1;
    int tri_num_d = 1;
    St_Triangle *tris_s = new St_Triangle[tri_num_s];
    St_Triangle *tris_d = new St_Triangle[tri_num_d];
    tris_s[0].x1 = (float)sx1/tex->width;
    tris_s[0].y1 = (float)sy1/tex->height;
    tris_s[0].x2 = (float)sx2/tex->width;
    tris_s[0].y2 = (float)sy2/tex->height;
    tris_s[0].x3 = (float)sx3/tex->width;
    tris_s[0].y3 = (float)sy3/tex->height;

    tris_d[0].x1 = dx1;
    tris_d[0].y1 = dy1;
    tris_d[0].x2 = dx2;
    tris_d[0].y2 = dy2;
    tris_d[0].x3 = dx3;
    tris_d[0].y3 = dy3;

    toVertexAttribBuff(1, tris_s, tris_d);
    delete[] tris_s;
    delete[] tris_d;
}

DrawTask::DrawTask(KmyITexture *tex,
                   int num, St_Rect *srects,
                   St_Rect2 *drects,
                   int z, float alpha, float angle){
    draw_type = DRAW_TYPE_IMAGE_PLURAL;
    this->tex = tex;
    this->z = z;
    this->alpha = alpha;
    this->angle = angle;

    point_num = num*6;
    int tri_num_s = num*2;
    int tri_num_d = num*2;
    St_Triangle *tris_s = new St_Triangle[tri_num_s];
    St_Triangle *tris_d = new St_Triangle[tri_num_d];
    for (int i=0; i<num; i++){
        rectToTri_s(tex, srects[i].x, srects[i].y, srects[i].w, srects[i].h,
                    drects[i].flip, &tris_s[i*2]);
        rectToTri_d(drects[i].x, drects[i].y, drects[i].w, drects[i].h,
                    &tris_d[i*2]);
    }
    toVertexAttribBuff(tri_num_d, tris_s, tris_d);
    delete[] tris_s;
    delete[] tris_d;
}

DrawTask::DrawTask(KmyITexture *tex,
                   St_Rect *srect, int dnum, St_Rect2 *drects,
                   int z, float alpha, float angle){
    draw_type = DRAW_TYPE_IMAGE_PLURAL;
    this->tex = tex;
    this->z = z;
    this->alpha = alpha;
    this->angle = angle;

    point_num = dnum*6;
    int tri_num_s = 2;
    int tri_num_d = dnum*2;
    St_Triangle *tris_s = new St_Triangle[tri_num_s];
    St_Triangle *tris_d = new St_Triangle[tri_num_d];
    rectToTri_s(tex, srect[0].x, srect[0].y, srect[0].w, srect[0].h,
                drects[0].flip, &tris_s[0]);

    for (int i=0; i<dnum; i++){
        rectToTri_d(drects[i].x, drects[i].y, drects[i].w, drects[i].h,
                    &tris_d[i*2]);
    }
    toVertexAttribBuff(tris_s, tri_num_d, tris_d);
    delete[] tris_s;
    delete[] tris_d;
}

DrawTask::~DrawTask(){
//    if (tri_num_s>0){
//        delete[] tris_s;
//        tris_s = NULL;
//    }
//    if (tri_num_d>0){
//        delete[] tris_d;
//        tris_d = NULL;
//    }
    delete[] texcroods;
    delete[] vertices;
}

void DrawTask::updateTexture(KmyITexture *tex){
    this->tex = tex;
}

void DrawTask::updateRegion(int sx, int sy, int sw, int sh,
                            int dx, int dy, int dw, int dh,
                            int z, float angle, int flip){
    point_num = 6;
    int tri_num_s = 2;
    int tri_num_d = 2;
    St_Triangle *tris_s = new St_Triangle[tri_num_s];
    St_Triangle *tris_d = new St_Triangle[tri_num_d];

    rectToTri_s(tex, sx, sy, sw, sh, flip, &tris_s[0]);

    rectToTri_d(dx, dy, dw, dh, &tris_d[0]);

    this->z = z;
    this->angle = angle;

    toVertexAttribBuff(tri_num_d, tris_s, tris_d);
    delete[] tris_s;
    delete[] tris_d;
}

void DrawTask::updatePlural(int num,
                            St_Rect *srects, St_Rect2 *drects,
                            int z, float alpha, float angle){
    this->z = z;
    this->alpha = alpha;
    this->angle = angle;

    point_num = num*6;
    int tri_num_s = num*2;
    int tri_num_d = num*2;
    St_Triangle *tris_s = new St_Triangle[tri_num_s];
    St_Triangle *tris_d = new St_Triangle[tri_num_d];
    for (int i=0; i<num; i++){
        rectToTri_s(tex, srects[i].x, srects[i].y, srects[i].w, srects[i].h,
                    drects[i].flip, &tris_s[i*2]);
        rectToTri_d(drects[i].x, drects[i].y, drects[i].w, drects[i].h,
                    &tris_d[i*2]);
    }
    toVertexAttribBuff(tri_num_d, tris_s, tris_d);
    delete[] tris_s;
    delete[] tris_d;
}

void DrawTask::updatePlural(St_Rect *srect, int num, St_Rect2 *drects,
                            int z, float alpha, float angle){
    this->z = z;
    this->alpha = alpha;
    this->angle = angle;

    point_num = num*6;
    int tri_num_s = 2;
    int tri_num_d = num*2;
    St_Triangle *tris_s = new St_Triangle[tri_num_s];
    St_Triangle *tris_d = new St_Triangle[tri_num_d];
    rectToTri_s(tex, srect[0].x, srect[0].y, srect[0].w, srect[0].h,
                drects[0].flip, &tris_s[0]);

    for (int i=0; i<num; i++){
        rectToTri_d(drects[i].x, drects[i].y, drects[i].w, drects[i].h,
                    &tris_d[i*2]);
    }
    toVertexAttribBuff(tris_s, tri_num_d, tris_d);
    delete[] tris_s;
    delete[] tris_d;
}

void DrawTask::updateAlpha(float alpha){
    this->alpha = alpha;
}

void DrawTask::updateAngle(float angle){
    this->angle = angle;
}

void DrawTask::rectToTri_s(KmyITexture *tex, int x, int y, int w, int h, int flip,
                         St_Triangle *tri){
    float x1 = (float)x/tex->width;
    float y1 = (float)y/tex->height;
    float x2 = (float)(x+w)/tex->width;
    float y2 = (float)(y+h)/tex->height;
    switch (flip){
    case 0:
        tri[0].x1 = x2;
        tri[0].y1 = y1;
        tri[0].x2 = x1;
        tri[0].y2 = y1;
        tri[0].x3 = x1;
        tri[0].y3 = y2;
        tri[1].x1 = x2;
        tri[1].y1 = y1;
        tri[1].x2 = x1;
        tri[1].y2 = y2;
        tri[1].x3 = x2;
        tri[1].y3 = y2;
        break;
    case 1: // x 翻转
        tri[0].x1 = x1;
        tri[0].y1 = y1;
        tri[0].x2 = x2;
        tri[0].y2 = y1;
        tri[0].x3 = x2;
        tri[0].y3 = y2;
        tri[1].x1 = x1;
        tri[1].y1 = y1;
        tri[1].x2 = x2;
        tri[1].y2 = y2;
        tri[1].x3 = x1;
        tri[1].y3 = y2;
        break;
    case 2: // y 翻转
        tri[0].x1 = x2;
        tri[0].y1 = y2;
        tri[0].x2 = x1;
        tri[0].y2 = y2;
        tri[0].x3 = x1;
        tri[0].y3 = y1;
        tri[1].x1 = x2;
        tri[1].y1 = y2;
        tri[1].x2 = x1;
        tri[1].y2 = y1;
        tri[1].x3 = x2;
        tri[1].y3 = y1;
        break;
    case 3: // xy 翻转
        tri[0].x1 = x;
        tri[0].y1 = y2;
        tri[0].x2 = x2;
        tri[0].y2 = y2;
        tri[0].x3 = x2;
        tri[0].y3 = y1;
        tri[1].x1 = x1;
        tri[1].y1 = y2;
        tri[1].x2 = x2;
        tri[1].y2 = y1;
        tri[1].x3 = x1;
        tri[1].y3 = y1;
        break;
    }
}


void DrawTask::rectToTri_d(int x, int y, int w, int h,
                           St_Triangle *tri){
    tri[0].x1 = x+w;
    tri[0].y1 = y;
    tri[0].x2 = x;
    tri[0].y2 = y;
    tri[0].x3 = x;
    tri[0].y3 = y+h;
    tri[1].x1 = x+w;
    tri[1].y1 = y;
    tri[1].x2 = x;
    tri[1].y2 = y+h;
    tri[1].x3 = x+w;
    tri[1].y3 = y+h;
}

void DrawTask::toVertexAttribBuff(int tri_num, St_Triangle *tris_s,
                                  St_Triangle *tris_d){
    texcroods = new float[tri_num*3*2];
    vertices = new float[tri_num*3*3];
    for (int i=0; i<tri_num; i++){
        texcroods[i*6]  =tris_s[i].x1;
        texcroods[i*6+1]=tris_s[i].y1;
        texcroods[i*6+2]=tris_s[i].x2;
        texcroods[i*6+3]=tris_s[i].y2;
        texcroods[i*6+4]=tris_s[i].x3;
        texcroods[i*6+5]=tris_s[i].y3;

        vertices[i*9]   =tris_d[i].x1;
        vertices[i*9+1] =tris_d[i].y1;
        vertices[i*9+2] =z;
        vertices[i*9+3] =tris_d[i].x2;
        vertices[i*9+4] =tris_d[i].y2;
        vertices[i*9+5] =z;
        vertices[i*9+6] =tris_d[i].x3;
        vertices[i*9+7] =tris_d[i].y3;
        vertices[i*9+8] =z;
    }
    uv_updated = true;
}

void DrawTask::toVertexAttribBuff(St_Triangle *tris_s, int tri_num, St_Triangle *tris_d){
    texcroods = new float[tri_num*3*2];
    vertices = new float[tri_num*3*3];
    for (int i=0; i<tri_num/2; i++){
        texcroods[i*12]  =tris_s[0].x1;
        texcroods[i*12+1]=tris_s[0].y1;
        texcroods[i*12+2]=tris_s[0].x2;
        texcroods[i*12+3]=tris_s[0].y2;
        texcroods[i*12+4]=tris_s[0].x3;
        texcroods[i*12+5]=tris_s[0].y3;
        texcroods[i*12+6]=tris_s[1].x1;
        texcroods[i*12+7]=tris_s[1].y1;
        texcroods[i*12+8]=tris_s[1].x2;
        texcroods[i*12+9]=tris_s[1].y2;
        texcroods[i*12+10]=tris_s[1].x3;
        texcroods[i*12+11]=tris_s[1].y3;
    }
    for (int i=0; i<tri_num; i++){
        vertices[i*9]   =tris_d[i].x1;
        vertices[i*9+1] =tris_d[i].y1;
        vertices[i*9+2] =z;
        vertices[i*9+3] =tris_d[i].x2;
        vertices[i*9+4] =tris_d[i].y2;
        vertices[i*9+5] =z;
        vertices[i*9+6] =tris_d[i].x3;
        vertices[i*9+7] =tris_d[i].y3;
        vertices[i*9+8] =z;
    }
    uv_updated = true;
}

DrawTaskChainNode::DrawTaskChainNode(DrawTask *dt){
    this->dt = dt;
    pre = NULL;
    next = NULL;
}
